home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
007
/
vt100tst.arc
/
VT100.C
next >
Wrap
Text File
|
1985-12-12
|
8KB
|
354 lines
/*
Having received many requests for my terminal emulator for the IBM PC,
here it is. It is written in C for the DeSmet C compiler, with assembler
for all the I/O routines. DeSmet's I/O library is big as a bus, and slow
to boot, so I simply avoid it. This program does very little, reasonably
well. New functions are easy to add. For folks with other compilers,
the only part likely to fail to work is the assembler for I/O: I put it
in-stream, using the "#asm" construct for in-stream assembler. You will
need to edit all assembler into an external assembler file, and invent
headers and trailers to implement the C calling convention for your compiler.
This program hasn't been prettied up for public consumption, but I am
painfully busy with other things, so in the hope that this is better
than nothing, here it is:
>From this to the next line of dashes is the document file for the program: */
/*------------------------------------------------------------------------------
Comm: a communication program for the IBM-PC
Comm is a minimal dumb terminal emulator for the IBM-PC under PC-DOS. It uses
BIOS function calls for keyboard input, allowing all control characters to be
sent with the conventional keyboard sequences. It uses an interrupt handler for
the communication port, functional up to 9600 baud. It is written in C with
assembler routines to handle I/O. It only supports the first asynchronous port,
COM1:. It doesn't support setting the communication parameters. This can be
done with the DOS "mode" command. The port IS NOT DISABLED (DTR is not dropped)
when the program is terminated; you must disconnect from the remote computer in
some other fashion. As a result, however, you can exit to DOS, make use of any
DOS commands which don't tinker with the communication port, and resume the
terminal session, without any disruption visible at the other end (characters
sent to the PC will be lost in the interim). Best of all, it is small. It
supports very few commands, all of which are alt sequences:
alt-e is a toggle: it turns echoing on and off (default off). This can be used
for half-duplex systems.
alt-v is a toggle: it turns verbose mode on and off (default off). In verbose
mode characters which are normally non-printable and aren't "carriage
control" characters print as "^x", where "x" is the character you would
hit to send the control character. Otherwise such chaff is ignored.
alt-b sends a break (approx. 300 ms. of line high)
alt-q quits the program, and returns to DOS
------------------------------------------------------------------------------
The program follows:
NOTE: this code is indented using tabs set every 4 columns, not 8.
------------------------------------------------------------------------------*/
/*
* Rudimentary communication program; written in C with I/O
* routines in assembler, using "#asm" construct in DeSmet C.
*/
#define TRUE 1
#define FALSE 0
#define NULL 0
#define comm_stat head!=tail
int head=0,
tail=0;
char comm_buffer[8192];
main()
{
char commget();
int c,
echo=FALSE,
verbose=FALSE;
initcomm();
goto inside;
while((c=my_ci())<256) /* alt's and function keys are >=256 */
{
commput(c);
if(echo)
my_co(c);
inside: while(my_stat()==0)
if(comm_stat)
if(is_nice(c=commget()))
my_co(c);
else
if(verbose)
{
my_co('^');
my_co(127&(c+'@'));
}
}
switch(c>>8) /* process function key */
{
case '\060': /* b send break */
make_break();
my_puts("** break **\n");
break;
case '\022': /* e echo toggle */
echo = !echo;
if(echo)
my_puts("** echo on **\n");
else
my_puts("** echo off **\n");
break;
case '\020': /* q quit */
my_puts("** returning to DOS **\n");
goto byebye;
case '\057': /* v verbose */
verbose = !verbose;
if(verbose)
my_puts("** verbose on **\n");
else
my_puts("** verbose off **\n");
break;
}
goto inside;
byebye:
killcomm();
}
initcomm()
{
#asm
; initialize communication port,
; and install interrupt handler
; save dseg for interrupt handler
mov ax,ds
mov cs:dssave,ax
; set int vector to my handler
push ds
xor ax,ax
mov ds,ax
mov [30h],offset handler
mov ax,cs
mov [32h],ax
pop ds
; assert DTR, RTS, and OUT2
mov dx,3fch
mov al,11
out dx,al
; enable interrupts for data ready
mov dx,3f9h
mov al,1
out dx,al
; clear any outstanding int
mov dx,3f8h
in al,dx
; enable interrupts
sti
; enable IRQ4 on 8259A
in al,21h
and al,0efh
out 21h,al
; and return
jmp init_finis
dssave: dw 0
handler:
push ds
push ax
push dx
push bx
; restore appropriate dseg
mov ax,cs:dssave
mov ds,ax
; grab the byte from comm port
mov dx,3f8h
in al,dx
; put it in the buffer
mov bx,tail_
mov comm_buffer_[bx],al
; tail=tail+1 (mod 8192)
inc bx
cmp bx,8192
jl handler_around
xor bx,bx
handler_around:
mov tail_,bx
; tell the 8259A EOI
mov dx,20h
mov al,32
out dx,al
pop bx
pop dx
pop ax
pop ds
; reenable interrupts
sti
iret
init_finis:
#
}
commput(c)
int c;
{
#asm
; put the character out the port
mov dx,3f8h
mov ax,[bp+4]
out dx,al
#
}
char commget()
{
char temp;
temp=comm_buffer[head++];
head%=8192;
return(temp);
}
killcomm()
{
#asm
; disconnect the interrupt handler
in al,21h
or al,10h
out 21h,al
#
}
make_break()
{
#asm
; set bit on LCR
mov dx,3fbh
in al,dx
push ax
or al,40h
out dx,al
; wait a wee bit (~200 ms)
mov bx,8
outer:
mov cx,7000
tight:
loop tight
dec bx
jnz outer
; and turn break back off
pop ax
out dx,al
#
}
is_nice(c) /* true for those characters that "should" be received */
char c;
{
c&=127;
if(c>=' ' && c<='~') /* printable */
return(TRUE);
if(c>6 && c<11) /* BEL, BS, HT, LF */
return(TRUE);
if(c==13 || c==27) /* CR, ESC */
return(TRUE);
return(FALSE);
}
my_puts(s) /* puts, using my_co() */
char *s;
{
while(*s)
{
if(*s=='\n')
my_co('\r');
my_co(*(s++));
}
}
my_co(c) /* character output, smaller and faster than DeSmet's,
using DOS function call 2.00 */
char c;
{
#asm
mov ah,2
mov dx,[bp+4]
int 21h
#
}
my_stat() /* true if character is ready from keyboard */
{
#asm
mov ah,1
int 16h
jz stat_no_char
mov ax,1
jmp stat_finis
stat_no_char:
xor ax,ax
stat_finis:
#
}
my_ci() /* get character from keyboard, using BIOS function call */
{
#asm
xor ah,ah
int 16h
or al,al
jz my_ci_finis
xor ah,ah
my_ci_finis:
#
}
------------------------------------------------------------------------------
The termcap for DOS 2.00 with ansi device driver follows:
------------------------------------------------------------------------------
pm|pcmon|IBM-PC using DOS 2.00 ansi device driver (monochrome)|\
:am:bc=^H:bw:ce=\E[K:cl=\E[2J:cm=\E[%i%d;%dH:co#80:cr=^M:\
:do=^J:ho=\E[H:kb=^H:li#25:ll=\E[25H:nd=\E[C:\
:pt:se=\E[0m:so=\E[1m:ta=^I:up=\E[A:xt:
pc|pccol|IBM-PC using DOS 2.00 ansi device driver (color)|\
:am:bc=^H:bw:ce=\E[K:cl=\E[2J:cm=\E[%i%d;%dH:co#80:cr=^M:\
:do=^J:ho=\E[H:kb=^H:li#25:ll=\E[25H:nd=\E[C:\
:pt:se=\E[0;32m:so=\E[1m:ta=^I:up=\E[A:xt:
------------------------------------------------------------------------------
and that's it! Enjoy. I place this in the public domain, and would appreciate
feedback. Improvements and bug reports especially desired. If the code is too
cryptic or uncommented, feel free to send questions to:
Bennett Todd
...{decvax,ihnp4,akgua}!mcnc!ecsvax!bet